home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_500 / wiconify / wiconify-source.lzh / Source / wGels.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  17KB  |  565 lines

  1. /*
  2.  *  WICONIFY    A utility that allows you to iconify any Intuition window
  3.  *              on any screen, and to open WB windows on any screen.
  4.  *
  5.  *  wGels.c     Handles the Bobs used when icons are dragged.
  6.  *
  7.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  8.  *  You may use this code, provided this copyright notice is kept intact.
  9.  */
  10.  
  11. #include "wHandler.h"
  12. #include <graphics/gels.h>
  13.  
  14.  
  15. static struct Bob *IconBob = NULL;      /* List of bobs being dragged */
  16. static WORD LastMouseX,LastMouseY;      /* Last place bobs were drawn */
  17.  
  18. static struct GelsInfo wGelsInfo;       /* Blank GelsInfo */
  19. static struct VSprite DummyA,DummyB;    /* Dummy sprites for GelsInfo */
  20.  
  21.  
  22. #define BOBSHADOW       BIT(0)          /* Means a shadow was allocated */
  23. #define BOBIMAGE        BIT(1)          /* Means an Image was allocated */
  24.  
  25.  
  26. /*
  27.  *  Macros for easy memory allocation/deallocation
  28.  */
  29.  
  30. #define NEWBOB(b)       NEWSTRUCT(Bob,b)
  31. #define FREEBOB(b)      FREESTRUCT(Bob,b)
  32.  
  33. #define NEWVSPRITE(s)   NEWSTRUCT(VSprite,s)
  34. #define FREEVSPRITE(s)  FREESTRUCT(VSprite,s)
  35.  
  36. #define NEWRASTER(s,i,d)  (s = AllocRaster((i)->Width,(i)->Height*d))
  37. #define FREERASTER(s,b,d) FreeRaster(s,SPRITE(b)->VUserExt,SPRITE(b)->Height*d)
  38.  
  39. #define NEWSHADOW(s,i)  NEWRASTER(s,i,1)
  40. #define FREESHADOW(b)   FREERASTER((b)->ImageShadow,b,1)
  41.  
  42. #define NEWSAVE(p,i,s)  NEWRASTER(p,i,s->BitMap.Depth)
  43. #define FREESAVE(b,s)   FREERASTER((b)->SaveBuffer,b,s->BitMap.Depth)
  44.  
  45. #define NEWIMAGE(s,i)   NEWRASTER(s,i,(i)->Depth)
  46. #define FREEIMAGE(b)    FREERASTER(SPRITE(b)->ImageData,b,SPRITE(b)->Depth)
  47.  
  48. #define SPRITE(b)       ((b)->BobVSprite)
  49.  
  50.  
  51.  
  52. /*
  53.  *  DrawGels()
  54.  *
  55.  *  Get the old screen GelsInfo and replace it by our own
  56.  *  Sort the Gels for the screen
  57.  *  Draw the icons on the screen
  58.  *  Put back the old GelsInfo
  59.  */
  60.  
  61. static void DrawGels(theScreen)
  62. WSCREEN *theScreen;
  63. {
  64.    struct GelsInfo *OldGI;
  65.  
  66.    Forbid();
  67.    OldGI = theScreen->Screen->RastPort.GelsInfo;
  68.    theScreen->Screen->RastPort.GelsInfo = &wGelsInfo;
  69.    SortGList(&(theScreen->Screen->RastPort));
  70.    DrawGList(&(theScreen->Screen->RastPort),&(theScreen->Screen->ViewPort));
  71.    theScreen->Screen->RastPort.GelsInfo = OldGI;
  72.    Permit();
  73. }
  74.  
  75.  
  76. /*
  77.  *  FreeBob()
  78.  *
  79.  *  If we have a bob to work with
  80.  *    If a shadow was allocated, free it
  81.  *    If a save buffer was allocated, free it
  82.  *    If the bob has a sprite
  83.  *      If the sprite image was allocated, free it
  84.  *      Free the sprite itself
  85.  *    Finally, free the bob
  86.  */
  87.  
  88. static void FreeBob(theBob,theScreen)
  89. struct Bob *theBob;
  90. WSCREEN *theScreen;
  91. {
  92.    if (theBob)
  93.    {
  94.       if (theBob->ImageShadow && (theBob->BUserExt & BOBSHADOW))
  95.           FREESHADOW(theBob);
  96.       if (theBob->SaveBuffer) FREESAVE(theBob,theScreen->Screen);
  97.       if (SPRITE(theBob))
  98.       {
  99.          if (SPRITE(theBob)->ImageData && (theBob->BUserExt & BOBIMAGE))
  100.             FREEIMAGE(theBob);
  101.          FREEVSPRITE(SPRITE(theBob));
  102.       }
  103.       FREEBOB(theBob);
  104.    }
  105. }
  106.  
  107.  
  108. /*
  109.  *  DisposeBobs()
  110.  *
  111.  *  While there are more bobs in the list
  112.  *     Free the bob and go on
  113.  *  Clear the list pointer
  114.  */
  115.  
  116. static void DisposeBobs(theScreen)
  117. WSCREEN *theScreen;
  118. {
  119.    struct Bob *theBob;
  120.    struct Bob *NextBob = IconBob;
  121.  
  122.    while ((theBob = NextBob) != NULL)
  123.    {
  124.       NextBob = theBob->After;
  125.       FreeBob(theBob,theScreen);
  126.    }
  127.    IconBob = NULL;
  128. }
  129.  
  130.  
  131. /*
  132.  *  MASK calculates the mask for the last word of the sprite data in each row
  133.  *  sw is the sprite width in words, bw is the width in pixels
  134.  */
  135.  
  136. #define MASK(bw,sw)     ~((1 << (sw * 16 - bw)) - 1)
  137.  
  138.  
  139. /*
  140.  *  MakeMask()
  141.  *
  142.  *  Get the Bob's sprite, and calculate its last image-data word
  143.  *  Calculate the last-word-of-row mask
  144.  *  Starting at the end of the sprite data, copy FFFF to each word
  145.  *  If the mask is not FFFF, go through and trim the final word of each
  146.  *    row to the correct mask value
  147.  */
  148.  
  149. static void MakeMask(theBob)
  150. struct Bob *theBob;
  151. {
  152.    struct VSprite *theSprite = SPRITE(theBob);
  153.    WORD  *last = theBob->ImageShadow + theSprite->Width * theSprite->Height - 1;
  154.    UWORD theMask = MASK(theSprite->VUserExt,theSprite->Width);
  155.    WORD  *w;
  156.    
  157.    for (w=last; w >= theBob->ImageShadow; w--) *w = 0xFFFF;
  158.    if (theMask != 0xFFFF)
  159.       for (w=last; w >= theBob->ImageShadow; w-=theSprite->Width) *w = theMask;
  160. }
  161.  
  162.  
  163. /*
  164.  *  NewBob()
  165.  *
  166.  *  Get the select imagery from the gadget
  167.  *  If we can allocate a new Bob structure
  168.  *    An a new VSPRITE structure
  169.  *      Add the sprite to the bob
  170.  *      Save the image width (in pixels) in the VUserExt field
  171.  *      If we can allocate a save buffer of the proper size
  172.  *        Set the sprite fields appropriately
  173.  *        Set the sprite's mask (use the Icon's one if it has one, 
  174.  *          otherwise, if this is a default image, use the default mask,
  175.  *          otherwise try to create a mask for the image, if possible
  176.  *          otherwise don't use a mask at all
  177.  *        Mark that everything went OK
  178.  *  If the Bob was not completely successful, free it and return NULL
  179.  */
  180.  
  181. static struct Bob *NewBob(theWGadget)
  182. struct wGadget *theWGadget;
  183. {
  184.    struct Gadget *theGadget = &(theWGadget->Gadget);
  185.    WICONREF *theIcon = (WICONREF *)theGadget->UserData;
  186.    struct Bob *theBob;
  187.    struct Image *theImage;
  188.    struct VSprite *theSprite;
  189.    short BobNotOK = TRUE;
  190.  
  191.    if (theGadget->Flags & GADGHIMAGE)
  192.       theImage = ((struct Image *)(theGadget->SelectRender));
  193.      else
  194.       theImage = ((struct Image *)(theGadget->GadgetRender));
  195.  
  196.    if (NEWBOB(theBob))
  197.    {
  198.       if (NEWVSPRITE(theBob->BobVSprite))
  199.       {
  200.          theSprite = SPRITE(theBob);
  201.          theSprite->VUserExt = theImage->Width;
  202.          if (NEWSAVE(theBob->SaveBuffer,theImage,theIcon->Screen->Screen))
  203.          {
  204.             theSprite->Flags     = SAVEBACK | OVERLAY;
  205.             theSprite->Height    = theImage->Height;
  206.             theSprite->Width     = (theImage->Width + 15) >> 4;
  207.             theSprite->Depth     = theImage->Depth;
  208.             theSprite->VSBob     = theBob;
  209.             theSprite->X         = theGadget->LeftEdge;
  210.             theSprite->Y         = theGadget->TopEdge;
  211.             if (theIcon->Icon.Mask)
  212.             {
  213.                theBob->ImageShadow = (WORD *)theIcon->Icon.Mask;
  214.             } else if ((theImage == DefaultImage || theImage == DefaultSelect)
  215.                          && theImage != NULL && DefaultMask) {
  216.                theBob->ImageShadow = DefaultMask->ImageData;
  217.             } else if ((theImage == DefaultScreenImage ||
  218.                         theImage == DefaultScreenSelect)
  219.                          && theImage != NULL && DefaultScreenMask) {
  220.                theBob->ImageShadow = DefaultScreenMask->ImageData;
  221.             } else if (NEWSHADOW(theBob->ImageShadow,theImage)) {
  222.                MakeMask(theBob);
  223.                theBob->BUserExt |= BOBSHADOW;
  224.             } else {
  225.                theSprite->Flags &= ~OVERLAY;
  226.             }
  227.             BobNotOK = FALSE;
  228.          }
  229.       }
  230.    }
  231.    if (BobNotOK)
  232.    {
  233.       FreeBob(theBob,theIcon->Screen);
  234.       theBob = NULL;
  235.    }
  236.    return(theBob);
  237. }
  238.  
  239.  
  240. /*
  241.  *  GetInvertedImage()
  242.  *
  243.  *  Get the Bob's sprite and its select imagery, if any
  244.  *  Get a pointer to the first gadget on the screen
  245.  *  Get a pointer to the first Bob in the list
  246.  *  If the gadget has a select image
  247.  *    Copy the image information to the sprite
  248.  *  Otherwise
  249.  *    Look through the gadget (an bob) list for a gadget with the same image
  250.  *    If the first one in the list is the gadget we are working on (ie, no 
  251.  *      other gadget has the same image)
  252.  *      Allocate a raster for the sprite's image, if possible
  253.  *        Set up dummy BitMaps to point to the sprite data and the image data
  254.  *        Get the size of the image to be copied, in pixels
  255.  *        Blit an inverted copy of the image into the sprite's data area
  256.  *        Mark that the image was allocated
  257.  *      Otherwise, use the image data area itself (may not be contiguous, tho!)
  258.  *      Copy the plane pick and on-off (inverted)
  259.  *    Otherwise (we found a gadget with the same image)
  260.  *      No need to make another copy, so just duplicate the old values
  261.  */
  262.  
  263. static void GetInvertedImage(theBob,theGadget,theScreen)
  264. struct Bob *theBob;
  265. struct Gadget *theGadget;
  266. WSCREEN *theScreen;
  267. {
  268.    struct VSprite *theSprite = SPRITE(theBob);
  269.    struct Image *theImage = (struct Image *)(theGadget->SelectRender);
  270.    struct wGadget *CheckGadget = theScreen->Selected;
  271.    struct Bob *CheckBob = IconBob;
  272.    struct BitMap SrcBitMap, DstBitMap;
  273.    long SizeX, SizeY;
  274.    char *SrcBytes;
  275.    char *DstBytes;
  276.    short i;
  277.  
  278.    if (theImage)
  279.    {
  280.       theSprite->ImageData = theImage->ImageData;
  281.       theSprite->PlanePick = theImage->PlanePick;
  282.       theSprite->PlaneOnOff = theImage->PlaneOnOff;
  283.    } else {
  284.       while (CheckGadget->Gadget.GadgetRender != theGadget->GadgetRender)
  285.       {
  286.          CheckGadget = CheckGadget->NextSelect;
  287.          CheckBob = CheckBob->After;
  288.       }
  289.       if (CheckGadget == (struct wGadget *)theGadget)
  290.       {
  291.          theImage = (struct Image *)(theGadget->GadgetRender);
  292.          if (NEWIMAGE(theSprite->ImageData,theImage))
  293.          {
  294.             SrcBytes = (char *) theImage->ImageData;
  295.             DstBytes = (char *) theSprite->ImageData;
  296.  
  297.             SrcBitMap.BytesPerRow  = theSprite->Width * 2;
  298.             SrcBitMap.Rows         = theSprite->Height;
  299.             SrcBitMap.Flags        = 0;
  300.             SrcBitMap.Depth        = theSprite->Depth;
  301.             for (i=0; i<SrcBitMap.Depth; i++)
  302.                SrcBitMap.Planes[i] = (PLANEPTR) (SrcBytes +
  303.                   (SrcBitMap.BytesPerRow * SrcBitMap.Rows) * i);
  304.  
  305.             DstBitMap.BytesPerRow = theSprite->Width * 2;
  306.             DstBitMap.Rows        = theSprite->Height;
  307.             DstBitMap.Flags       = 0;
  308.             DstBitMap.Depth       = theSprite->Depth;
  309.             for (i=0; i<DstBitMap.Depth; i++)
  310.                DstBitMap.Planes[i] = (PLANEPTR) (DstBytes +
  311.                   (DstBitMap.BytesPerRow * DstBitMap.Rows) * i);
  312.  
  313.             SizeX = SrcBitMap.BytesPerRow * 8;
  314.             SizeY = SrcBitMap.Rows;
  315.             #define BLT_COPYINVERT   0x30
  316.             BltBitMap(&SrcBitMap,0L,0L,&DstBitMap,0L,0L,SizeX,SizeY,
  317.                BLT_COPYINVERT,0xFF,NULL);
  318.       
  319.             theBob->BUserExt |= BOBIMAGE;
  320.          } else {
  321.             theSprite->ImageData = theImage->ImageData;
  322.          }
  323.          theSprite->PlanePick = theImage->PlanePick;
  324.          theSprite->PlaneOnOff = ~(theImage->PlaneOnOff);
  325.       } else {
  326.          theSprite->ImageData  = CheckBob->BobVSprite->ImageData;
  327.          theSprite->PlanePick  = CheckBob->BobVSprite->PlanePick;
  328.          theSprite->PlaneOnOff = CheckBob->BobVSprite->PlaneOnOff;
  329.       }
  330.    }
  331. }
  332.  
  333.  
  334. /*
  335.  *  CreateBobs()
  336.  *
  337.  *  Get the old GelsInfo from the screen
  338.  *  Init our GelsInfo and place it in the screen
  339.  *  While ther are selected gadgets to look at
  340.  *    If the gadget is allowed tobe moved
  341.  *      If we can get a new bob for the gadget
  342.  *        Add the bob to the end of the bob list
  343.  *        Get its inverted imagery (or select imagery if it has it)
  344.  *        Add the bob to the screen
  345.  *    Go on to the next selected gadget
  346.  *  Put back the old GelsInfo
  347.  */
  348.  
  349. static void CreateBobs(theScreen)
  350. WSCREEN *theScreen;
  351. {
  352.    struct wGadget *theGadget = theScreen->Selected;
  353.    struct Bob *theBob;
  354.    struct Bob *LastBob = NULL;
  355.    struct GelsInfo *OldGI;
  356.  
  357.    Forbid();
  358.    OldGI = theScreen->Screen->RastPort.GelsInfo;
  359.    InitGels(&DummyA,&DummyB,&wGelsInfo);
  360.    theScreen->Screen->RastPort.GelsInfo = &wGelsInfo;
  361.    while (theGadget)
  362.    {
  363.       if ((GADGETICON->Icon.Flags & (WI_NOMOVE| WI_LOCKED)) == FALSE)
  364.       {
  365.          if (theBob = NewBob(theGadget))
  366.          {
  367.             if (IconBob == NULL) IconBob = theBob;
  368.             if (LastBob) LastBob->After = theBob;
  369.             theBob->After = NULL;
  370.             theBob->Before = LastBob;
  371.             LastBob = theBob;
  372.             GetInvertedImage(theBob,theGadget,theScreen);
  373.             AddBob(theBob,&(theScreen->Screen->RastPort));
  374.          }
  375.       }
  376.       theGadget = theGadget->NextSelect;
  377.    }
  378.    theScreen->Screen->RastPort.GelsInfo = OldGI;
  379.    Permit();
  380. }
  381.  
  382.  
  383. /*
  384.  *  RemoveBobs()
  385.  *
  386.  *  While there are more bobs in the list
  387.  *    Request that the bob be removed from the screen
  388.  *  Draw the gels list (to remove the bobs)
  389.  *  If the screen's layers were locked, unlock them
  390.  *  Free the memory used by the bobs
  391.  */
  392.  
  393. static void RemoveBobs(theScreen)
  394. WSCREEN *theScreen;
  395. {
  396.    struct Bob *theBob = IconBob;
  397.  
  398.    while (theBob)
  399.    {
  400.       RemBob(theBob);
  401.       theBob = theBob->After;
  402.    }
  403.    DrawGels(theScreen);
  404.    if (theScreen->Flags & WI_LAYERLOCK)
  405.    {
  406.       UnlockLayers(&(theScreen->Screen->LayerInfo));
  407.       theScreen->Flags &= ~WI_LAYERLOCK;
  408.    }
  409.    DisposeBobs(theScreen);
  410. }
  411.  
  412.  
  413. /*
  414.  *  SetBobPosition()
  415.  *
  416.  *  While ther are more bobs in the list
  417.  *    Change the position of the bob and go on to the next one
  418.  */
  419.  
  420. static void SetBobPosition(dx,dy)
  421. WORD dx,dy;
  422. {
  423.    struct Bob *theBob = IconBob;
  424.  
  425.    while (theBob)
  426.    {
  427.       theBob->BobVSprite->X += dx;
  428.       theBob->BobVSprite->Y += dy;
  429.       theBob = theBob->After;
  430.    }
  431. }
  432.  
  433.  
  434. /*
  435.  *  StartDragging()
  436.  *
  437.  *  Add RMBTRAP to the backdrop window flags (no menus during dragging)
  438.  *  Add MOUSEMOVEs to the desired Intuition events
  439.  *  Mark the screen to start dragging on the first mouse move
  440.  *  Record the mouse position so that move offsets can be calculated
  441.  */
  442.  
  443. void StartDragging(theIcon,MouseX,MouseY)
  444. WICONREF *theIcon;
  445. WORD MouseX,MouseY;
  446. {
  447.    Forbid();
  448.    theIcon->Screen->BackDrop->Flags |= RMBTRAP;
  449.    ModifyIDCMP(theIcon->Screen->BackDrop,IDCMPFLAGS | MOUSEMOVE);
  450.    theIcon->Screen->Flags |= WI_STARTDRAG;
  451.    LastMouseX = MouseX;
  452.    LastMouseY = MouseY;
  453.    Permit();
  454. }
  455.  
  456.  
  457. /*
  458.  *  CancelDragging()
  459.  *
  460.  *  If the screen has icons dragging or is waiting to drag
  461.  *    If there are bobs, remove them
  462.  *    Reset the RMPTRAP flag so menus will work again
  463.  *    Remove the MOUSEMOVE IDCMP flag
  464.  *    Clear the dragging flags for the screen
  465.  */
  466.  
  467. void CancelDragging(theScreen)
  468. WSCREEN *theScreen;
  469. {
  470.    Forbid();
  471.    if (theScreen->Flags & (WI_DRAGGING | WI_STARTDRAG))
  472.    {
  473.       if (IconBob) RemoveBobs(theScreen);
  474.       theScreen->BackDrop->Flags &= ~RMBTRAP;
  475.       ModifyIDCMP(theScreen->BackDrop,IDCMPFLAGS);
  476.       theScreen->Flags &= ~(WI_DRAGGING | WI_STARTDRAG);
  477.    }
  478.    Permit();
  479. }
  480.  
  481.  
  482. /*
  483.  *  EndDragging()
  484.  *
  485.  *  If there are bobs and they have been dragged
  486.  *    Find the layer where the mouse is pointing
  487.  *    If the layer is the screen's backdrop wIconify window, then
  488.  *       Move the bobs to their final positions
  489.  *       Get the change in position of the bobs (from their initial locations)
  490.  *       Remove the bobs from the screen
  491.  *       While there are gadgets to be updated
  492.  *         If the gadget is movable, set its new position
  493.  *         Go on to the next selected gadget
  494.  *     Otherwise (icons dropped into some other window)
  495.  *       Remove the bobs
  496.  *       Show an error message and "beep" the screen.
  497.  *  Cancel the dragging
  498.  */
  499.  
  500. void EndDragging(theScreen,MouseX,MouseY)
  501. WSCREEN *theScreen;
  502. WORD MouseX,MouseY;
  503. {
  504.    struct wGadget *theGadget = theScreen->Selected;
  505.    struct Layer *theLayer;
  506.    WORD dx,dy;
  507.    extern struct Layer *WhichLayer();
  508.  
  509.    if (IconBob && (theScreen->Flags & WI_DRAGGING))
  510.    {
  511.       theLayer = WhichLayer(&(theScreen->Screen->LayerInfo),
  512.          MouseX,MouseY + theScreen->BackDrop->TopEdge);
  513.       if (theLayer && (struct Window *)theLayer->Window == theScreen->BackDrop)
  514.       {
  515.          SetBobPosition(MouseX-LastMouseX,MouseY-LastMouseY);
  516.          dx = IconBob->BobVSprite->X - theGadget->Gadget.LeftEdge;
  517.          dy = IconBob->BobVSprite->Y - theGadget->Gadget.TopEdge;
  518.          RemoveBobs(theScreen);
  519.          while (theGadget)
  520.          {
  521.             if ((GADGETICON->Icon.Flags & (WI_NOMOVE| WI_LOCKED)) == FALSE)
  522.                MoveGadget(theGadget,dx,dy,theScreen);
  523.             theGadget = theGadget->NextSelect;
  524.          }
  525.       } else {
  526.          RemoveBobs(theScreen);
  527.          IconError("Icons can't be moved to that window!");
  528.          DisplayBeep(theScreen->Screen);
  529.       }
  530.    }
  531.    CancelDragging(theScreen);
  532. }
  533.  
  534.  
  535. /*
  536.  *  MoveGels()
  537.  *
  538.  *  If the bobs have not yet been dragged
  539.  *    Create the bob list
  540.  *    If there are bobs to drag
  541.  *      Lock the screen layers
  542.  *      Mark the screen as locked and dragging
  543.  *  Move the bobs to their new position
  544.  *  Save the current mouse position for later
  545.  *  Draw the bobs in their new location
  546.  */
  547.  
  548. void MoveGels(theScreen,MouseX,MouseY)
  549. WSCREEN *theScreen;
  550. WORD MouseX,MouseY;
  551. {
  552.    if ((theScreen->Flags & WI_DRAGGING) == FALSE)
  553.    {
  554.       CreateBobs(theScreen);
  555.       if (IconBob)
  556.       {
  557.          LockLayers(&(theScreen->Screen->LayerInfo));
  558.          theScreen->Flags |= WI_DRAGGING | WI_LAYERLOCK;
  559.       }
  560.    }
  561.    SetBobPosition(MouseX-LastMouseX,MouseY-LastMouseY);
  562.    LastMouseX = MouseX; LastMouseY = MouseY;
  563.    DrawGels(theScreen);
  564. }
  565.